package com.atguigu.srb.core.controller.admin;


import com.alibaba.excel.EasyExcel;
import com.atguigu.srb.base.exception.SrbException;
import com.atguigu.srb.base.result.ResponseEnum;
import com.atguigu.srb.base.result.ResponseVo;
import com.atguigu.srb.base.util.SrbAssert;
import com.atguigu.srb.core.pojo.entity.Dict;
import com.atguigu.srb.core.pojo.vo.DictExcelVO;
import com.atguigu.srb.core.service.DictService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.joda.time.DateTime;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 数据字典 前端控制器
 * </p>
 *
 * @author muzhao
 * @since 2024-08-19
 */
@RestController
@Slf4j
//访问时 如果路径错误 或 请求方式错误 或 请求参数错误 都可能导致跨域问题
//@CrossOrigin //允许跨域
@RequestMapping("/admin/core/dict")
@Api(tags = "系统设置模块")
public class AdminDictController {
    @Resource
    DictService dictService;

    /*
        处理上传的数据字典excel：解析excel数据保存到数据字典表 每一行代表一个数据字典对象
        1.创建JavaBean接收excel数据
        2.创建回调监听器：处理解析到的每行数据
        3.使用EasyExcel读取数据
     */
    //由于前端文件上传使用的时请求体，所以这里的请求方式不可以使用GetMapping
    @ApiOperation("导入数据字典")
    @PostMapping("/import")
    public ResponseVo importDicts(@RequestParam("excel") MultipartFile file) { //前端上传的文件的表单项name值需要设置为fule 默认方式才可以接收
        dictService.importDicts(file);
        return ResponseVo.ok().message("文件上传成功");
    }

    @ApiOperation("导出数据字典")
    @GetMapping("/export")
    public void exportDicts(HttpServletResponse response) { //实际上就是文件下载
        try {
            //设置响应报文响应体内容的类型+编码+文件名
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            String fileName = URLEncoder.encode("数据字典_"+new DateTime().toString("yyyy-MM-dd-HH-mm-ss"), "UTF-8").replaceAll("\\+", "%20");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
            //查询数据
            List<DictExcelVO> dictExcelVOS = dictService.list().stream().map(dict -> {
                DictExcelVO dictExcelVO = new DictExcelVO();
                BeanUtils.copyProperties(dict, dictExcelVO);
                return dictExcelVO;
            }).collect(Collectors.toList());
            //向response对象的输出流中写入数据
            EasyExcel.write(response.getOutputStream())
                    .sheet("数据字典")
                    .head(DictExcelVO.class)
                    .doWrite(dictExcelVOS);
        } catch (IOException e) {
            e.printStackTrace();
            throw new SrbException(ResponseEnum.EXPORT_DATA_ERROR);
        }
    }

    @ApiOperation("查询一级数据字典的集合并判断其是否含有子数据字典")
    @GetMapping("parent/{pid}") //使用pid查询一组数据字典(一级数据字典pid=0)
    public ResponseVo parent(@PathVariable("pid") Long pid){
        List<Dict> dicts = dictService.parent(pid);
        return ResponseVo.ok().data("items",dicts);
    }

    @ApiOperation("根据id删除数据字典")
    @DeleteMapping("{id}")
    public ResponseVo deleteById(@PathVariable("id") Long id){
        //如果删除的数据字典存在下一级 无法删除
        SrbAssert.assertNotTrue(dictService.hasChildren(id),ResponseEnum.HAS_CHILDREN_ERROR);
        //删除
        SrbAssert.assertTrue(dictService.removeById(id),ResponseEnum.ERROR);
        return ResponseVo.ok().message("删除成功");
    }

    @ApiOperation("根据id查询数据字典")
    @GetMapping("{id}")
    public ResponseVo getById(@PathVariable("id") Long id){
        Dict dict = dictService.getById(id);
        return ResponseVo.ok().data("item",dict);
    }

    @ApiOperation("更新数据字典")
    @PutMapping
    public ResponseVo updateById(@RequestBody Dict dict){
        SrbAssert.assertTrue(dictService.updateById(dict),ResponseEnum.ERROR);
        return ResponseVo.ok().message("更新成功");
    }

    @ApiOperation("新增数据字典")
    @PostMapping
    public ResponseVo save(@RequestBody Dict dict){
        SrbAssert.assertTrue(dictService.saveChildDict(dict),ResponseEnum.ERROR);
        return ResponseVo.ok().message("新增成功");
    }
}

